package common

import (
	"fmt"
	"sort"
	"gopkg.in/mgo.v2/bson"
	"reflect"
	"crypto/sha1"
	"crypto/hmac"
	"crypto/md5"
	"golang.org/x/net/websocket"
	"bufio"
	"time"
	"unicode/utf8"
	"encoding/hex"
	"net/http"
)
//从一段字符串中匹配关键字
//keys为关键字数组，content为字符串内容，返回一个字符串数组
func MatchKeysFromString(keys[] string, content string) []string {
	trie := NewTrie()
	for i := range  keys {
		trie.Insert(keys[i])
	}
	root := trie.GetRoot()
	matchWords := make([]string, 0)
	str := []rune(content)
	for i := range str {
		match := matchKeys(root, "", str, i)
		if match != "" {
			matchWords = append(matchWords, match)
		}
	}
	return matchWords
}

func matchKeys(node* TreeNode , str string, content[] rune, i int) string {
	if len(content) <= i {
		return ""
	}
	if node.isEnd {
		return str
	}
	v := fmt.Sprintf("%c", content[i])
	if node.son[v] != nil {
		return matchKeys(node.son[v], str + v, content, i + 1)
	}
	return ""
}

func Reverse(values sort.Interface) {
	len := values.Len()
	if len == 0 {
		return
	}
	for i := 0; i <= len / 2 ; i++ {
		values.Swap(i, len - 1 - i)
	}
	return
}
//目前只支持slice
func ConverId2ObjectId(ids interface{}, name string) []bson.ObjectId {
	objIds := []bson.ObjectId{}
	t := reflect.ValueOf(ids)
	if t.Kind() != reflect.Slice {
		return objIds
	}
	len := t.Len()
	if len == 0 {
		return objIds
	}
	for i := 0; i < len; i++ {
		objIds = append(objIds, bson.ObjectIdHex(t.Index(i).Elem().FieldByName(name).String()))
	}
	return objIds
}
//遍历一个slice，每条执行handle函数
func EachSliceWithFunc(values []*interface{}, handle func(index int, value interface{})) {
	for i, v := range values {
		handle(i, v)
	}
}

func HmacSha1(str string, key string) string {
	mac := hmac.New(sha1.New, []byte(key))
	mac.Write([]byte(str))
	return fmt.Sprintf("%x", mac.Sum(nil))
}

func HashMD5(str string) string {
	md5 := md5.New()
	md5.Write([]byte(str))
	return fmt.Sprintf("%s", hex.EncodeToString(md5.Sum(nil)))
}

func UT8Encode(str string) string {
	ret := ""
	rs := []rune(str)
	for _, r := range rs {
		by := make([]byte, 10)
		write := utf8.EncodeRune(by, r)
		for i := 0; i < write; i++ {
			ret += string(by[0:write])
		}
	}
	return ret
}

//订阅全部a股
func SubcribeStock(ws *websocket.Conn)  {
	w := bufio.NewWriter(ws)
	w.Write([]byte(SendMessage(bson.M{
		"url": "/block/obj",
		"qs": bson.M{
			"gql": "block=股票\\\\市场分类\\\\全部A股",
			"sub": "1",
			"qid": "0",
		},
	})))
	w.Flush()
}

func SubcribeTheme(ws * websocket.Conn)  {
	w := bufio.NewWriter(ws)
	w.Write([]byte(SendMessage(bson.M{
		"url": "/sort/range",
		"qs": bson.M{
			"market": "B$",
			"field": "ZhongWenJianCheng",
			"sub": "1",
			"qid": "0",
		},
	})))
	w.Flush()
}

func SendMessage(m bson.M) string {
	url := m["url"]
	msg := url.(string) + "?"
	qs := m["qs"].(bson.M)
	for k, v := range qs {
		msg += fmt.Sprintf("%s=%s&", k, v)
	}
	r := []rune(msg)
	return string(r[0:len(r) - 1])
}

func InitNextId() string {
	return time.Now().Format("2006_01_02") + "0"
}

func PrintURLMiddleWare(r *http.Request) string {
	//获取method
	method := r.Method
	//获取path
	url := r.URL.Path
	if err := r.ParseForm(); err != nil {
		logger.Error(err)
	}
	return fmt.Sprintf("%s %s", method, url)
}

func SubStr(str string, start int, end int) string {
	strChars := []rune(str)
	if start > end {
		return ""
	}
	if len(strChars) < end {
		return ""
	}
	return string(strChars[start:end])
}

func StrLength(str string) int {
	return len([]rune(str))
}